package com.digua.base.base

import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.res.TypedArray
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
import android.view.LayoutInflater
import android.view.Window
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
import com.alibaba.fastjson2.JSON
import com.digua.base.listener.RegisterForActivityResultListener
import com.digua.base.util.AuthorizeUtil
import com.digua.base.util.LogUtil
import org.greenrobot.eventbus.EventBus
import java.io.Serializable
import java.lang.reflect.ParameterizedType

open class Activity<UI : ViewBinding> : AppCompatActivity(), RegisterForActivityResultListener {
    lateinit var ui: UI
    lateinit var ctx: Activity<UI>
    var ctx1: Context? = null
    private lateinit var launcher: ActivityResultLauncher<Intent>
    private var callback: ActivityResultCallback<Intent>? = null
    protected var isBusMsg = false
    protected var isShow = false

    override fun onCreate(savedInstanceState: Bundle?) {
        //兼容处理
        compatibleProcessing()
        super.onCreate(savedInstanceState)
        ctx = this
        requestWindowFeature(Window.FEATURE_NO_TITLE)
        try {
            if (javaClass.genericSuperclass is ParameterizedType) {
                val type = javaClass.genericSuperclass as ParameterizedType
                val cls = type.actualTypeArguments[0] as Class<*>
                val inflate = cls.getDeclaredMethod("inflate", LayoutInflater::class.java)
                ui = inflate.invoke(null, layoutInflater) as UI
                setContentView(ui.root)
            }
        } catch (e: java.lang.Exception) {
            LogUtil.e("异常:", e)
        }
        if (isBusMsg) EventBus.getDefault().register(this)
        launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { callback?.apply { onActivityResult(it.data!!) } }
    }

    protected open fun <T : android.app.Activity> startActivity(clz: Class<T>, data: Any? = null) {
        val intent = Intent(this, clz)
        data?.let {
            when (data) {
                is Serializable -> intent.putExtra("data", it as Serializable)
                is Parcelable -> intent.putExtra("data", it as Parcelable)
                is Intent -> intent.putExtras(it as Intent)
                is Bundle -> intent.putExtras(it as Bundle)
                else -> intent.putExtra("data", JSON.toJSONString(data))
            }
        }
        startActivity(intent)
    }

    protected open fun <T : android.app.Activity> startActivityFinish(clz: Class<T>, data: Any? = null) {
        startActivity(clz, data)
        finish()
    }

    override fun startActivity(intent: Intent?) {
        if (!AuthorizeUtil.checkActivity()) return
        super.startActivity(intent)
    }

    override fun startActivity(intent: Intent?, options: Bundle?) {
        if (!AuthorizeUtil.checkActivity()) return
        super.startActivity(intent, options)
    }

    /**
     * 兼容处理
     */
    private fun compatibleProcessing() {
        //针对android8.x时，界面背景设置为透明或半透明时；BUG： Only fullscreen activities can request orientation
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O && isTranslucentOrFloating()) {
            LogUtil.d("给8.x系统的界面固定方向 = ${fixOrientation()}")
        }
    }

    //固定方向
    private fun fixOrientation(): Boolean {
        try {
            val field = android.app.Activity::class.java.getDeclaredField("mActivityInfo")
            //android.app.Activity.field
            field.isAccessible = true
            val o = field[this] as ActivityInfo
            o.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
            field.isAccessible = false
            return true
        } catch (e: Exception) {
            LogUtil.e("异常:", e)
        }
        return false
    }

    //判断是否是半透明的还是浮动的
    private fun isTranslucentOrFloating(): Boolean {
        var isTranslucentOrFloating = false
        try {
            val styleableRes = Class.forName("com.android.internal.R\$styleable").getField("Window")[null] as IntArray
            val ta = obtainStyledAttributes(styleableRes)
            val m = ActivityInfo::class.java.getMethod("isTranslucentOrFloating", TypedArray::class.java)
            m.isAccessible = true
            isTranslucentOrFloating = m.invoke(null, ta) as Boolean
            m.isAccessible = false
        } catch (e: Exception) {
            LogUtil.e("异常:", e)
        }
        return isTranslucentOrFloating
    }

    //设置请求的方向
    override fun setRequestedOrientation(requestedOrientation: Int) {
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O && isTranslucentOrFloating()) {
            LogUtil.d("避免在 Oreo 时调用 setRequestedOrientation。")
            return
        }
        super.setRequestedOrientation(requestedOrientation)
    }

    override fun onResume() {
        super.onResume()
        isShow = true
    }

    override fun onPause() {
        super.onPause()
        isShow = false
    }

    override fun onDestroy() {
        super.onDestroy()
        if (isBusMsg) EventBus.getDefault().unregister(this)
    }

    override fun finish() {
        if (!AuthorizeUtil.checkActivity()) return
        super.finish()
    }

    override fun registerForActivityResult(intent: Intent, callback: ActivityResultCallback<Intent>) {
        this.callback = callback
        launcher.launch(intent)
    }

}